1 module unde.global_state;
2 
3 import unde.games.dizzy.omega.main;
4 import unde.file_manager.events;
5 import unde.keybar.lib;
6 
7 import std.format;
8 import std.conv;
9 import std.stdio;
10 
11 import std.datetime;
12 
13 import std.string;
14 
15 import derelict.sdl2.sdl;
16 import derelict.sdl2.image;
17 
18 import derelict.opengl3.gl3;
19 import derelict.opengl3.gl;
20 import derelict.sdl2.mixer;
21 
22 public import core.sys.posix.sys.types;
23 
24 import std.file;
25 
26 struct Games
27 {
28     DizzyOmega dizzy_omega;
29 }
30 
31 class GlobalState
32 {
33     Games games;
34     SDL_Window* window;
35     SDL_Renderer* renderer;
36     bool finish = false;
37     uint frame; //Frame which renders
38     uint time; //Time from start of program in ms
39     uint fps_frames;
40     uint fps_time;
41 
42     bool window_shown;
43 
44     KeyBar_Buttons keybar;
45     SDL_Rect screen;
46 
47     void createWindow(size_t display = 0)
48     {
49         int displays = SDL_GetNumVideoDisplays();
50 
51         int x = SDL_WINDOWPOS_UNDEFINED;
52         int y = SDL_WINDOWPOS_UNDEFINED;
53 
54         if (display > 0 && display < displays)
55         {
56             SDL_Rect displayBounds;
57             auto r = SDL_GetDisplayBounds(cast(int) display, &displayBounds);
58             if (r != 0)
59             {
60                 writefln("Error SDL_GetDisplayBounds display %d: %s", display, SDL_GetError().fromStringz());
61             }
62             else
63             {
64                 x = displayBounds.x;
65                 y = displayBounds.y;
66             }
67         }
68 
69         SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 4);
70         //The window we'll be rendering to
71         window = SDL_CreateWindow(
72             "Dizzy Omega",                            // window title
73             x,                                 // initial x position
74             y,                                 // initial y position
75             0,                                 // width, in pixels
76             0,                                 // height, in pixels
77             SDL_WINDOW_FULLSCREEN_DESKTOP | 
78             SDL_WINDOW_RESIZABLE |
79             SDL_WINDOW_OPENGL                  // flags
80         );
81         if( window == null )
82         {
83             throw new Exception(format("Error while create window: %s",
84                     SDL_GetError().to!string()));
85         }
86     }
87 
88     void createRenderer()
89     {
90         /* To render we need only renderer (which connected to window) and
91            surfaces to draw it */
92         SDL_SetHint(SDL_HINT_RENDER_DRIVER, "opengl");
93         renderer = SDL_CreateRenderer(
94                 window, 
95                 -1, 
96                 SDL_RENDERER_ACCELERATED | SDL_RENDERER_TARGETTEXTURE
97         );
98         if (!renderer)
99         {
100             writefln("Error while create accelerated renderer: %s",
101                     SDL_GetError().to!string());
102             renderer = SDL_CreateRenderer(
103                     window, 
104                     -1, 
105                     SDL_RENDERER_TARGETTEXTURE
106             );
107         }
108         if (!renderer)
109         {
110             throw new Exception(format("Error while create renderer: %s",
111                     SDL_GetError().to!string()));
112         }
113 
114         SDL_RenderClear(renderer);
115 
116         SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
117 
118         int r = SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_BLEND);
119         if (r < 0)
120         {
121             throw new Exception(
122                     format("Error while set render draw blend mode: %s",
123                     SDL_GetError().to!string()));
124         }
125 
126         SDL_bool res = SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "1");
127         if (!res)
128         {
129             throw new Exception(
130                     format("Can't set filter mode"));
131         }
132     }
133 
134     void initGL()
135     {
136         DerelictGL.load();
137         DerelictGL3.load();
138         DerelictGL3.reload();
139 
140         glEnable(GL_BLEND);
141         glEnable(GL_TEXTURE_2D);
142         glEnable(GL_LIGHTING);
143         glEnable(GL_LIGHT0);
144         glLightfv(GL_LIGHT0, GL_POSITION, [-5f, -5f, 10.0f, 1.0f].ptr);
145         glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, [0.5f, 0.5f, -1.0f].ptr);
146         glLighti(GL_LIGHT0, GL_SPOT_EXPONENT, 64);
147         glLighti(GL_LIGHT0, GL_SPOT_CUTOFF, 90);
148 
149         glEnable(GL_LIGHT1);
150         glLightfv(GL_LIGHT1, GL_DIFFUSE, [0.0f, 0.08f, 0.10f, 1.0f].ptr);
151         glLightfv(GL_LIGHT1, GL_SPECULAR, [0.0f, 0.0f, 0.0f, 1.0f].ptr);
152         glLightfv(GL_LIGHT1, GL_POSITION, [0.0f, 0.0f, 0.0f, 1.0f].ptr);
153         //glLightfv(GL_LIGHT1, GL_SPOT_DIRECTION, [0.5f, 0.5f, -1.0f].ptr);
154         glLighti(GL_LIGHT1, GL_SPOT_EXPONENT, 90);
155         glLighti(GL_LIGHT1, GL_SPOT_CUTOFF, 180);
156         glLighti(GL_LIGHT1, GL_CONSTANT_ATTENUATION, 0);
157         glLighti(GL_LIGHT1, GL_QUADRATIC_ATTENUATION, 3);
158 
159         glEnable(GL_LIGHT2);
160         glLightfv(GL_LIGHT2, GL_DIFFUSE, [0.0f, 0.08f, 0.10f, 1.0f].ptr);
161         glLightfv(GL_LIGHT2, GL_SPECULAR, [0.0f, 0.0f, 0.0f, 1.0f].ptr);
162         glLightfv(GL_LIGHT2, GL_POSITION, [0.0f, 0.0f, 0.0f, 1.0f].ptr);
163         //glLightfv(GL_LIGHT1, GL_SPOT_DIRECTION, [0.5f, 0.5f, -1.0f].ptr);
164         glLighti(GL_LIGHT2, GL_SPOT_EXPONENT, 90);
165         glLighti(GL_LIGHT2, GL_SPOT_CUTOFF, 180);
166         glLighti(GL_LIGHT2, GL_CONSTANT_ATTENUATION, 0);
167         glLighti(GL_LIGHT2, GL_QUADRATIC_ATTENUATION, 1);
168 
169         glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
170         glEnable(GL_NORMALIZE);
171 
172         glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
173     }
174 
175     void syncTime()
176     {
177         time = SDL_GetTicks();
178     }
179 
180     void startGame()
181     {
182         if (games.dizzy_omega is null)
183         {
184             games.dizzy_omega = new DizzyOmega(this);
185         }
186         games.dizzy_omega.toGame(this);
187         setup_keybar(this);
188     }
189 
190     void stopGame()
191     {
192         games.dizzy_omega.fromGame(this);
193         finish = true;
194     }
195 
196     void initSDL(size_t display = 0)
197     {
198         DerelictSDL2.load();
199         
200         if( SDL_Init( SDL_INIT_VIDEO | SDL_INIT_TIMER ) < 0 )
201         {
202             throw new Exception(format("Error while SDL initializing: %s",
203                     SDL_GetError().to!string() ));
204         }
205 
206         createWindow(display);
207 
208         createRenderer();
209 
210         SDL_GetWindowSize(window, &screen.w, &screen.h);
211 
212         initGL();
213 
214         screen.w -= 32*6;
215     }
216 
217     void deInitSDL()
218     {
219         SDL_DestroyRenderer(renderer);
220         SDL_DestroyWindow(window);
221         SDL_Quit();
222     }
223 
224     void initSDLImage()
225     {
226         DerelictSDL2Image.load();
227 
228         auto flags = IMG_INIT_PNG;
229         int initted = IMG_Init(flags);
230         if((initted&flags) != flags) {
231             if (!(IMG_INIT_PNG & initted))
232                 writefln("IMG_Init: Failed to init required png support!");
233             throw new Exception(format("IMG_Init: %s\n",
234                         IMG_GetError().to!string()));
235         }
236     }
237 
238     void initSDLMixer()
239     {    
240         DerelictSDL2Mixer.load();
241  	
242         // load support for the OGG sample/music formats
243         int flags=MIX_INIT_OGG;
244         int initted=Mix_Init(flags);
245         if((initted&flags) != flags) {
246             if (!(MIX_INIT_OGG & initted))
247                 writefln("Mix_Init: Failed to init required ogg support!");
248             throw new Exception(format("IMG_Init: %s\n",
249                         Mix_GetError().to!string()));
250         }
251 
252         if(Mix_OpenAudio(44100, MIX_DEFAULT_FORMAT, 2, 1024)==-1) {
253             throw new Exception(format("Mix_OpenAudio: %s\n",
254                         Mix_GetError().to!string()));
255         }
256     }
257 
258     void initAllSDLLibs(size_t display = 0)
259     {
260         initSDLImage();
261         initSDLMixer();
262         initSDL(display);
263     }
264 
265     void deInitAllSDLLibs()
266     {
267         Mix_CloseAudio();
268         Mix_Quit();
269         IMG_Quit();
270         deInitSDL();
271     }
272 
273     this(bool force_recover = false, size_t display = 0)
274     {
275         initAllSDLLibs(display);
276         keybar = new KeyBar_Buttons(this, renderer, null);
277         startGame();
278     }
279 
280     ~this()
281     {
282         stopGame();
283         deInitAllSDLLibs();
284     }
285 }
286